﻿using SnakeGame.Lesson1;
using SnakeGame.Lesson3;
using SnakeGame.Lesson4;
using SnakeGame.Lesson5;
using System;

namespace SnakeGame.Lesson6
{
    internal enum E_MoveDirection
    {
        Up,
        Down,
        Left,
        Right
    }

    internal class Snake : IDarw
    {
        private readonly SnakeBody[] bodys;

        // 蛇头的方向
        private E_MoveDirection direction = E_MoveDirection.Right;

        // 记录当前蛇身的长度
        private int snakelength = 4;

        public Snake(int x, int y)
        {
            // 粗暴声明蛇长度的数组
            //int maxLength = (Game.height - 3) * (Game.width - 3);
            int maxLength = 100;
            bodys = new SnakeBody[maxLength];
            // 蛇头
            bodys[0] = new SnakeBody(x, y, E_SnakeBodyType.Head);
            // 蛇身长度
            for (int i = 1; i < snakelength; i++)
            {
                // 蛇身
                bodys[i] = new SnakeBody(x - i * 2, y, E_SnakeBodyType.Body);
            }
        }

        public void Draw()
        {
            for (int i = 0; i < snakelength; i++)
            {
                bodys[i].Draw();
            }
        }

        #region 移动和转向

        // 蛇移动
        public void Move()
        {
            // 移动前擦除最后一个位置
            SnakeBody lastbody = bodys[snakelength - 1];
            Console.SetCursorPosition(lastbody.position.x, lastbody.position.y);
            Console.Write("  ");
            // 移动蛇身
            for (int i = snakelength - 1; i > 0; i--)
            {
                bodys[i].position = bodys[i - 1].position;
            }
            // 擦除后，移动蛇身
            switch (direction)
            {
                case E_MoveDirection.Up:
                    bodys[0].position.y--;
                    break;

                case E_MoveDirection.Down:
                    bodys[0].position.y++;
                    break;

                case E_MoveDirection.Left:
                    bodys[0].position.x -= 2;
                    break;

                case E_MoveDirection.Right:
                    bodys[0].position.x += 2;
                    break;
            }
        }

        // 蛇转向
        public void SetDirection(E_MoveDirection newDirection)
        {
            // 防止直接反向
            if ((direction == E_MoveDirection.Up && newDirection == E_MoveDirection.Down) ||
                (direction == E_MoveDirection.Down && newDirection == E_MoveDirection.Up) ||
                (direction == E_MoveDirection.Left && newDirection == E_MoveDirection.Right) ||
                (direction == E_MoveDirection.Right && newDirection == E_MoveDirection.Left))
            {
                return;
            }
            direction = newDirection;
        }

        #endregion 移动和转向

        #region 碰撞检测

        // 食物碰撞检测
        public bool CheckFoodCollision(Position pos)
        {
            for (int i = 0; i < snakelength; i++)
            {
                if (bodys[i].position == pos)
                {
                    return true;
                }
            }
            return false;
        }

        // 碰撞检测
        public bool IsCollision(Map map)
        {
            // 蛇头碰撞墙体检测
            for (int i = 0; i < map.walls.Length; i++)
            {
                if (bodys[0].position == map.walls[i].position)
                {
                    return true;
                }
            }
            // 蛇头碰撞蛇身检测
            for (int i = 1; i < snakelength; i++)
            {
                if (bodys[0].position == bodys[i].position)
                {
                    return true;
                }
            }
            return false;
        }

        #endregion 碰撞检测

        #region 食物相关

        // 吃到食物
        public bool EatFood(Food food)
        {
            if (food.position == bodys[0].position)
            {
                // 重新生成食物
                food.RandomPosition(this);
                // 增加蛇身长度
                AddBody();
                return true;
            }
            return false;
        }
        
        public void AddBody()
        {
            // 增加蛇身长度
            bodys[snakelength] = new SnakeBody(bodys[snakelength - 1].position.x, bodys[snakelength - 1].position.y, E_SnakeBodyType.Body);
            // 增加长度
            try
            {
                snakelength++;
                // 可能会越界
                if (snakelength >= bodys.Length)
                {
                    throw new IndexOutOfRangeException("蛇身长度超过最大值！");
                }
            }
            catch (IndexOutOfRangeException e)
            {
                Console.WriteLine(e.Message);
            }
        }

        #endregion 食物相关
    }
}